#include "esp_log.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "esp_http_client.h"
// #include "esp_tls.h"
#include "esp_crt_bundle.h"
#include "cJSON.h"
#include "sys/sgf_cfg.h"
#include "sgf_http.h"

static const char *TAG = "http";
extern sgf_cfg_t sgf_cfg;
#define DEFAULT_KEY "5771a3b3de47b4f1175ab1131f99dbcc"

esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    static char *output_buffer;  // Buffer to store response of http request from event handler
    static int output_len;       // Stores number of bytes read
    switch(evt->event_id) {
        case HTTP_EVENT_ERROR:
            ESP_LOGD(TAG, "HTTP_EVENT_ERROR");
            break;
        case HTTP_EVENT_ON_CONNECTED:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED");
            break;
        case HTTP_EVENT_HEADER_SENT:
            ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT");
            break;
        case HTTP_EVENT_ON_HEADER:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER, key=%s, value=%s", evt->header_key, evt->header_value);
            break;
        case HTTP_EVENT_ON_DATA:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
            if (!esp_http_client_is_chunked_response(evt->client)) {
                if (evt->user_data) {
                    memcpy(evt->user_data + output_len, evt->data, evt->data_len);
                } else {
                    if (output_buffer == NULL) {
                        output_buffer = (char *) malloc(esp_http_client_get_content_length(evt->client));
                        output_len = 0;
                        if (output_buffer == NULL) {
                            ESP_LOGE(TAG, "Failed to allocate memory for output buffer");
                            return ESP_FAIL;
                        }
                    }
                    memcpy(output_buffer + output_len, evt->data, evt->data_len);
                }
                output_len += evt->data_len;
            }

            break;
        case HTTP_EVENT_ON_FINISH:
            ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH");
            if (output_buffer != NULL) {
                free(output_buffer);
                output_buffer = NULL;
            }
            output_len = 0;
            break;
        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
            break;
    }
    return ESP_OK;
}

static int sgf_get_adcode(char *buff, char *code)
{
    int ret = -1;
    cJSON *root;
    cJSON *js_status;
    cJSON *js_adcode;
    char *status, *adcode;
    root = cJSON_Parse(buff);
    if (root) {
        js_status = cJSON_GetObjectItem(root, "status");
        if (js_status) {
            status = cJSON_GetStringValue(js_status);
            ESP_LOGI(TAG, "http status %s", status);
            if (strcmp(status, "1") == 0) {
                js_adcode = cJSON_GetObjectItem(root, "adcode");
                if (js_adcode) {
                    adcode = cJSON_GetStringValue(js_adcode);
                    ESP_LOGI(TAG, "[%s:%d]adcode:%s", __FUNCTION__, __LINE__, adcode);
                    strcpy(code, adcode);
                    ret = 0;
                }
                cJSON_Delete(root);
                return ret;
            }
        }
        cJSON_Delete(root);
    }
    return ret;
}

int get_week(int y,int m, int d)
{
    if(m==1||m==2) {
        m+=12;
        y--;
    }
    int week=(d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;
    return week;
}

static int sgf_get_weather(char *buff, sgf_info_t *info)
{
    cJSON *root;
    cJSON *js_status, *live;
    cJSON *js_city;
    cJSON *js_weather, *js_temp, *js_date;
    char *status, *city, *temp, *weather, *date;
    root = cJSON_Parse(buff);
    if (root) {
        js_status = cJSON_GetObjectItem(root, "status");
        if (js_status) {
            status = cJSON_GetStringValue(js_status);
            ESP_LOGI(TAG, "http status %s", status);
            if (strcmp(status, "1") == 0) {
                live = cJSON_GetArrayItem(cJSON_GetObjectItem(root, "lives"), 0);
                js_city = cJSON_GetObjectItem(live, "city");
                js_temp = cJSON_GetObjectItem(live, "temperature");
                js_weather = cJSON_GetObjectItem(live, "weather");
                js_date = cJSON_GetObjectItem(live, "reporttime");
            
                weather = cJSON_GetStringValue(js_weather);
                temp = cJSON_GetStringValue(js_temp);
                city = cJSON_GetStringValue(js_city);
                date = cJSON_GetStringValue(js_date);
                sscanf(date, "%04d-%02d-%02d", &info->year, &info->mon, &info->mday);
                ESP_LOGI(TAG, "http year=%d mon=%d, day=%d", info->year, info->mon, info->mday);
                strncpy(info->weather.city, city, 20);
                strncpy(info->weather.daytemp, temp, 20);
                strncpy(info->weather.dayweather, weather, 20);
                info->wday = get_week(info->year, info->mon, info->mday);
                cJSON_Delete(root);
                return 0;
            }
        }
        cJSON_Delete(root);
    }
    return -1;
}

static int sgf_get_code(char *buff, sgf_info_t *info)
{
    cJSON *root;
    cJSON *js_hitokoto;
    char *hitokoto;
    root = cJSON_Parse(buff);
    if (root) {
        js_hitokoto = cJSON_GetObjectItem(root, "hitokoto");
        if (js_hitokoto) {
            hitokoto = cJSON_GetStringValue(js_hitokoto);
            if (strlen(hitokoto)) {
                strcpy(info->remind, hitokoto);
                return 0;
            }
        }
        cJSON_Delete(root);
    }
    return -1;
}
int sgf_http_get_adcode(char *adcode, char *key)
{
    int ret = 0;
    char local_response_buffer[2048] = {0};
    char query[200] = { 0 };
    if (strlen(key) <= 0) {
        sprintf(query, "key=%s", DEFAULT_KEY);
    } else {
        sprintf(query, "key=%s", key);
    }

    esp_http_client_config_t config = {
        .host = "restapi.amap.com",
        .path = "/v3/ip",
        .event_handler = http_event_handler,
        .user_data = local_response_buffer,
        .disable_auto_redirect = true,
    };
    config.query = &query;
    ESP_LOGI(TAG, "[%s:%d]query:%s", __FUNCTION__, __LINE__, config.query);
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_method(client, HTTP_METHOD_GET);
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET adcode Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
        ret = sgf_get_adcode(local_response_buffer, adcode);
    } else {
        ESP_LOGE(TAG, "HTTP GET adcode request failed: %s", esp_err_to_name(err));
        ret = -1;
    }
    return ret;
}

int sgf_http_get_weather(sgf_info_t *info, char *adcode, char *key)
{
    char local_response_buffer[2048] = {0};
    char query[300] = { 0 };
    if (strlen(adcode) <= 0) {
        if (sgf_http_get_adcode(adcode, key) < 0) {
            ESP_LOGE(TAG, "HTTP GET adcode request failed");
            return -1;
        }
        strcpy(sgf_cfg.http.code, adcode);
        sgf_cfg_write(&sgf_cfg);
    }
    
    esp_http_client_config_t config = {
        .host = "restapi.amap.com",
        .path = "/v3/weather/weatherInfo",
        .event_handler = http_event_handler,
        .user_data = local_response_buffer,
        .disable_auto_redirect = true,
    };
    if (strlen(key) <= 0) {
        sprintf(query, "key=%s&city=%s", DEFAULT_KEY, "310100");
    } else {
        ESP_LOGI(TAG, "key=%s, code", key, adcode);
        sprintf(query, "key=%s&city=%s", key, adcode);
    }
    config.query = &query;
    ESP_LOGI(TAG, "[%s:%d]query:%s", __FUNCTION__, __LINE__, config.query);

    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_method(client, HTTP_METHOD_GET);
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
        sgf_get_weather(local_response_buffer, info);
    } else {
        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    ESP_LOG_BUFFER_HEX(TAG, local_response_buffer, strlen(local_response_buffer));
    esp_http_client_cleanup(client);
    return 0;
}

int sgf_http_get_code(sgf_info_t *info, char *type)
{
    // https://www.ooopn.com/tool/api/yan/api.php?type=json
    char local_response_buffer[2048] = {0};
    char query[300] = { 0 };
    
    esp_http_client_config_t ttconfig = {
        .url = "https://v1.hitokoto.cn",
        // .path = "/tool/api/yan/api.php",
        .event_handler = http_event_handler,
        .user_data = local_response_buffer,
        .crt_bundle_attach = esp_crt_bundle_attach,
        // .disable_auto_redirect = false,
    };
    // if (strlen(type) <= 0) {
        // sprintf(query, "type=%s", "json");
    // } else {
    //     sprintf(query, "type=%s", type);
    // }
    // ttconfig.query = &query;
    // ESP_LOGI(TAG, "[%s:%d]query:%s", __FUNCTION__, __LINE__, ttconfig.query);

    esp_http_client_handle_t client = esp_http_client_init(&ttconfig);
    // esp_http_client_set_method(client, HTTP_METHOD_GET);
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d",
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
        sgf_get_code(local_response_buffer, info);
    } else {
        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    ESP_LOG_BUFFER_HEX(TAG, local_response_buffer, strlen(local_response_buffer));
    esp_http_client_cleanup(client);
    return 0;
}